package com.dlc.felear.xiaoensale.helper;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.dlc.felear.xiaoensale.R;
import com.dlc.felear.xiaoensale.constant.Constant;
import com.dlc.felear.xiaoensale.dlc_serial_port.DlcSerialPortClient;
import com.dlc.felear.xiaoensale.entity.NextStep;
import com.dlc.felear.xiaoensale.factory.CmdList;
import com.dlc.felear.xiaoensale.utils.RecordLog;

import org.simple.eventbus.EventBus;

import java.util.ArrayList;
import java.util.concurrent.ScheduledExecutorService;

public class LiaoHeHelper implements Handler.Callback {
    private static final String TAG = "LiaoHeHelper";
    private static final int WHAT_CLOSE = 9247;
    private static final int WHAT_OPEN = 9248;
    private final int IO_CLOSE_VALUE = 0;
    private final int IO_OPEN_VALUE = 255;
    private final int CloseDelay = 60;
    private boolean isWork = false;
    private byte gtTop_sensor = 2;
    private IoOutHelper ioOutHelper;
    private IoInputHelper inputHelper;
    private String serialNum;
    private byte io_lh_zz = 4;
    private byte io_lh_fz = 5;

    private byte io_gz_1_zz = 6;
    private byte io_gz_1_fz = 7;
    private byte io_gz_2_zz = 8;
    private byte io_gz_2_fz = 9;
    private byte io_gz_3_zz = 10;
    private byte io_gz_3_fz = 11;
    private byte io_gz_4_zz = 12;
    private byte io_gz_4_fz = 13;

    private final byte io_gz_1_colse = 10;
    private final byte io_gz_1_open = 11;
    private final byte io_gz_2_colse = 12;
    private final byte io_gz_2_open = 13;
    private final byte io_gz_3_colse = 14;
    private final byte io_gz_3_open = 15;
    private final byte io_gz_4_colse = 16;
    private final byte io_gz_4_open = 17;

    private final long liaohe_delay = 15000;
    private final long gezi_open_delay = 2000;
    private final long gezi_close_delay = 5000;
    private final byte io_lh_top_sensor = 6;
    private final byte io_lh_bottom_sensor = 7;
    private Handler handler;
    private ScheduledExecutorService scheduledThreadPool;
    private ArrayList<NextStep> nextSteps;
    private GuotiHelper guotiHelper;
    /**
     * 0 表示不知道当前位置
     */
    private int moudel = 0;


    public LiaoHeHelper(IoOutHelper ioOutHelper, IoInputHelper inputHelper,
                        String serialNum, ScheduledExecutorService scheduledThreadPool) {
        this.ioOutHelper = ioOutHelper;
        this.inputHelper = inputHelper;
        this.serialNum = serialNum;
        nextSteps = new ArrayList<>();
        this.scheduledThreadPool = scheduledThreadPool;
        handler = new Handler(this);
    }

    public void setGuotiHelper(GuotiHelper guotiHelper) {
        this.guotiHelper = guotiHelper;
    }

    private void liaoHeTop() {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (guotiHelper.getPosition(gtTop_sensor) == 0) {
                    log("锅体未复位,不能翻转料盒", 1);
                    sendToastMsg("锅体未复位,不能翻转料盒");
                    return;
                }
                if (!allGzCloseStatus()) {
                    log("格子门未关好，不能翻转料盒", 1);
                    sendToastMsg("格子门未关好,不能翻转料盒");
                    return;
                }
                if (inputHelper.getIoStatus(io_lh_top_sensor) == 0) {
                    if (ioOutHelper.getIoStatus(io_lh_zz) == 0) {
                        huchiIo(io_lh_fz, io_lh_zz, liaohe_delay);
                    } else {
                        log("料盒正在朝上转动", 0);
                    }
                } else {
                    log("料盒已经在朝上位置", 0);
                }
            }
        });
    }

    private void liaoHeBottom() {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (guotiHelper.getPosition(gtTop_sensor) == 0) {
                    log("锅体未复位,不能翻转料盒", 1);
                    sendToastMsg("锅体未复位,不能翻转料盒");
                    return;
                }
                if (!allGzCloseStatus()) {
                    log("格子门未关好，不能翻转料盒", 1);
                    sendToastMsg("格子门未关好,不能翻转料盒");
                    return;
                }
                if (inputHelper.getIoStatus(io_lh_bottom_sensor) == 0) {
                    if (ioOutHelper.getIoStatus(io_lh_fz) == 0) {
                        huchiIo(io_lh_zz, io_lh_fz, liaohe_delay);
                    } else {
                        log("料盒正在朝下转动", 0);
                    }
                } else {
                    log("料盒已经在朝下位置", 0);
                }
            }
        });
    }



    /**
     * 打开格子前位置判断
     *
     * @param num
     * @param openTime
     */
    public void handleGz(final byte num, final byte openTime) {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                log("格子:" + num + " 打开时间=" + openTime, 0);
                isWork = true;
                if (num == 0) {
                    liaoHeBottom();
                    return;
                }
                if (num >= 5) {
                    if(num==5){
                        liaoHeTop();
                    }
                    if(num==11){
                        closeGezi();
                    }
                    return;
                }
                if (inputHelper.getIoStatus(io_lh_bottom_sensor) == 1) {
                    //判断料盒是否朝下
                    openGz(num, openTime);
                } else {
                    liaoHeBottom();
                    nextSteps.add(new NextStep(num, (byte) IO_CLOSE_VALUE, openTime));
                }
            }
        });
    }

    /**
     * 打开格子
     *
     * @param num
     * @param openTime
     */
    private void openGz(final byte num, final long openTime) {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (num > 4 || num < 1) {
                    log("格子编码错误", 1);
                    sendToastMsg("格子编码错误");
                    return;
                }
                byte num1 = 0;
                if (num == 1) {
                    num1 = 7;
                } else if (num == 2) {
                    num1 = 9;
                } else if (num == 3) {
                    num1 = 11;
                } else if (num == 4) {
                    num1 = 13;
                }
                if (!checkCloseStatus(num)&&inputHelper.getIoStatus((byte) (num1 + 4))==1) {
                    log("检测到格子" + num + "已经打开", 0);
                    Message message = new Message();
                    message.what = WHAT_OPEN;
                    message.obj = new NextStep((byte) (num1 - 1), (byte) IO_OPEN_VALUE, gezi_open_delay);
                    sendHandlerMsg(message, 10000);
                    return;
                }
                if (ioOutHelper.getIoStatus(num1) == 1) {
                    log("检测格子" + num + "正在打开", 0);

                    return;
                }
                log("打开格子信息 num:" + num + " 打开时间:" + openTime, 0);
                guotiHelper.stopActionDelay();
                long openTime1 = openTime * 1000;
                if (inputHelper.getIoStatus((byte) (num1 + 4)) == 0) {
                    huchiIo((byte) (num1 - 1), num1, 5000);
                    Message message = new Message();
                    message.what = WHAT_OPEN;
                    message.obj = new NextStep((byte) (num1 - 1), (byte) IO_OPEN_VALUE, gezi_open_delay);
                    sendHandlerMsg(message, openTime1);
                    log("关闭格子 num:" + (num1 - 1) + " 延迟关闭时间:" + openTime1, 0);
                } else {
                    log("该格子已经打开了：num=" + num1, 0);

                }

            }
        });
    }

    private boolean checkCloseStatus(byte num) {
        if (num == 1 && inputHelper.getIoStatus(io_gz_1_colse) == 1) {
            log("格子:" + num + "已经打开", 0);
            return true;
        }
        if (num == 2 && inputHelper.getIoStatus(io_gz_2_colse) == 1) {
            log("格子:" + num + "已经打开", 0);
            return true;
        }
        if (num == 3 && inputHelper.getIoStatus(io_gz_3_colse) == 1) {
            log("格子:" + num + "已经打开", 0);
            return true;
        }
        if (num == 4 && inputHelper.getIoStatus(io_gz_4_colse) == 1) {
            log("格子:" + num + "已经打开", 0);
            return true;
        }
        return false;
    }

    /**
     * 触发传感器处理
     *
     * @param num
     */
    public void sensorStatus(final byte num) {
        log("触发X" + num, 0);
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (!isWork) {
                    return;
                }
                switch (num) {
                    case io_lh_top_sensor:
                        liaoHeStop();
                        break;
                    case io_lh_bottom_sensor:
                        liaoHeStop();
                        handleNextStep();
                        break;
                    case io_gz_1_colse:
                        sendDelayCloseIoMsg(WHAT_CLOSE, io_gz_1_zz, CloseDelay + 100);
                        break;
                    case io_gz_1_open:
                        controlOutputIo(io_gz_1_fz, IO_CLOSE_VALUE);
                        break;
                    case io_gz_2_colse:
                        sendDelayCloseIoMsg(WHAT_CLOSE, io_gz_2_zz, CloseDelay);
                        break;
                    case io_gz_2_open:
                        controlOutputIo(io_gz_2_fz, IO_CLOSE_VALUE);
                        break;
                    case io_gz_3_colse:
                        sendDelayCloseIoMsg(WHAT_CLOSE, io_gz_3_zz, CloseDelay);
                        break;
                    case io_gz_3_open:
                        controlOutputIo(io_gz_3_fz, IO_CLOSE_VALUE);
                        break;
                    case io_gz_4_colse:
                        sendDelayCloseIoMsg(WHAT_CLOSE, io_gz_4_zz, CloseDelay);
                        break;
                    case io_gz_4_open:
                        controlOutputIo(io_gz_4_fz, IO_CLOSE_VALUE);
                        break;
                }
            }
        });
    }

    private void handleNextStep() {
        if (!nextSteps.isEmpty()) {
            for (NextStep nextStep : nextSteps) {
                openGz(nextStep.getNum(), nextStep.getDelayTime());
                nextSteps.remove(nextStep);
            }
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (WHAT_CLOSE == msg.what) {
            controlOutputIo((byte) msg.arg1, IO_CLOSE_VALUE);
        } else if (WHAT_OPEN == msg.what) {
            NextStep nextStep = (NextStep) msg.obj;
            log("what="+JsonHelper.toJson(nextStep),0);
            if (nextStep != null) {
                checkGeziStatus(nextStep);
            }
        }
        return false;
    }


    private void sendHandlerMsg(Message message, long delayTime) {
        handler.sendMessageDelayed(message, delayTime);
    }

    /**
     * 检测格子门关闭情况
     *
     * @param nextStep
     */
    private void checkGeziStatus(NextStep nextStep) {
        log("关闭格子序号:"+nextStep.getNum()+" 关闭传感器状态:"+inputHelper.getIoStatus(io_gz_1_colse),0);
        if (nextStep.getNum() == 6 && inputHelper.getIoStatus(io_gz_1_colse) != 1) {
            controlOutputIo(nextStep.getNum(), IO_OPEN_VALUE);
            sendDelayCloseIoMsg(WHAT_CLOSE, nextStep.getNum(), gezi_close_delay);
        }
        if (nextStep.getNum() == 8 && inputHelper.getIoStatus(io_gz_2_colse) != 1) {
            controlOutputIo(nextStep.getNum(), IO_OPEN_VALUE);
            sendDelayCloseIoMsg(WHAT_CLOSE, nextStep.getNum(), gezi_close_delay);
        }
        if (nextStep.getNum() == 10 && inputHelper.getIoStatus(io_gz_3_colse) != 1) {
            controlOutputIo(nextStep.getNum(), IO_OPEN_VALUE);
            sendDelayCloseIoMsg(WHAT_CLOSE, nextStep.getNum(), gezi_close_delay);
        }
        if (nextStep.getNum() == 12 && inputHelper.getIoStatus(io_gz_4_colse) != 1) {
            controlOutputIo(nextStep.getNum(), IO_OPEN_VALUE);
            sendDelayCloseIoMsg(WHAT_CLOSE, nextStep.getNum(), gezi_close_delay);
        }

    }


    private void log(String msg, int level) {
        RecordLog.getInstance().saveLog(msg);
        Log.e(TAG, msg);
    }

    /**
     * 料盒停止翻转
     */
    private void liaoHeStop() {
        controlOutputIo(io_lh_fz, 0);
        controlOutputIo(io_lh_zz, 0);
    }


    private void huchiIo(final byte stopIo, final byte runIo, final long closeDelay) {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    controlOutputIo(stopIo, IO_CLOSE_VALUE);
                    Thread.sleep(100);
                    controlOutputIo(runIo, IO_OPEN_VALUE);
                    sendDelayCloseIoMsg(WHAT_CLOSE, runIo, closeDelay);
                } catch (Exception e) {

                }
            }
        });
    }

    public void looper() {
        try {
//            closeGezi();
        } catch (Exception e) {

        }
    }

    /**
     * 关闭所有格子
     */
    private void closeGezi() {
        log("io_gz_1_colse="+inputHelper.getIoStatus(io_gz_1_colse),0);
        log("io_gz_2_colse="+inputHelper.getIoStatus(io_gz_2_colse),0);
        log("io_gz_3_colse="+inputHelper.getIoStatus(io_gz_3_colse),0);
        log("io_gz_4_colse="+inputHelper.getIoStatus(io_gz_4_colse),0);
        if (inputHelper.getIoStatus(io_gz_1_colse) == 0) {
            controlOutputIo((byte) 6, IO_OPEN_VALUE);
            sendDelayCloseIoMsg(WHAT_CLOSE, (byte) 6, 5000);
        }
        if (inputHelper.getIoStatus(io_gz_2_colse) == 0) {
            controlOutputIo((byte) 8, IO_OPEN_VALUE);
            sendDelayCloseIoMsg(WHAT_CLOSE, (byte) 8, 5000);
        }
        if (inputHelper.getIoStatus(io_gz_3_colse) == 0) {
            controlOutputIo((byte) 10, IO_OPEN_VALUE);
            sendDelayCloseIoMsg(WHAT_CLOSE, (byte) 10, 5000);
        }
        if (inputHelper.getIoStatus(io_gz_4_colse) == 0) {
            controlOutputIo((byte) 12, IO_OPEN_VALUE);
            sendDelayCloseIoMsg(WHAT_CLOSE, (byte) 12, 5000);
        }
    }

    /**
     * 延迟关闭
     *
     * @param num
     * @param time
     */
    private void sendDelayCloseIoMsg(int what, int num, long time) {
        Message message = new Message();
        message.what = what;
        message.arg1 = num;
        message.arg2 = num >= 26 ? 3 : 2;
        handler.sendMessageDelayed(message, time);
    }

    /**
     * io状态控制
     *
     * @param num
     * @param value
     */
    private void controlOutputIo(final byte num, final int value) {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (num >= 26) {
                    sendCmd(serialNum, CmdList.controlOutputIo(3, num - 26, value));
                } else {
                    sendCmd(serialNum, CmdList.controlOutputIo(2, num, value));
                }
            }
        });

    }

    private void sendCmd(String serialNo, byte[] data) {
        ioOutHelper.addCmdToQueque(data);
//        DlcSerialPortClient.getInstance().send(serialNo, data);
    }

    /**
     * 获取设备异常信息
     *
     * @return
     */
    public String devceiStatus() {
        if (inputHelper.getIoStatus(io_lh_top_sensor) != 1) {
            return "料盒斗位置异常";
        }
        if (inputHelper.getIoStatus(io_gz_1_colse) != 1) {
            return "料盒格子1门异常";
        }
        if (inputHelper.getIoStatus(io_gz_2_colse) != 2) {
            return "料盒格子2门异常";
        }
        if (inputHelper.getIoStatus(io_gz_3_colse) != 3) {
            return "料盒格子3门异常";
        }
        if (inputHelper.getIoStatus(io_gz_4_colse) != 4) {
            return "料盒格子4门异常";
        }
        return "";
    }

    /**
     * 判断格子是否全部关好
     *
     * @return
     */
    public boolean allGzCloseStatus() {
        if (inputHelper.getIoStatus(io_gz_1_colse) == 1 && inputHelper.getIoStatus(io_gz_2_colse) == 1
                && inputHelper.getIoStatus(io_gz_3_colse) == 1 && inputHelper.getIoStatus(io_gz_4_colse) == 1) {
            return true;
        }
        return false;
    }

    public boolean isTopPosition(){
        return inputHelper.getIoStatus(io_lh_top_sensor)==1;
    }
    public boolean isBottomPosition(){
        return inputHelper.getIoStatus(io_lh_bottom_sensor)==1;
    }

    private void sendToastMsg(String msg) {
        EventBus.getDefault().post(msg, Constant.DEVICE_STATUS_MSG_SHOW);
    }

}
